home *** CD-ROM | disk | FTP | other *** search
- /*
- Scaling, Rotation, Antialiasing prototyper. revision 3.
-
- This program was written by Lewis A. Sellers (Minimalist)
- of The Minimalist Group, and the MOSOCI Grail Project in
- 1995-1996 Anno Dominus.
-
- While it is the result of several days of work on my part, fiddled
- with here and there over a few months as time permits, you can use
- it and the code involved if you wish as intas you include the standard
- greetings to me somewhere in your program, say in the credits.
-
- You must supply a BMP filename as an argument such as:
- C:> ALIAS DEATH.BMP
- The BMP can be any size, grayscale or color, so long as it is 8-bit color.
-
- This originally was written with borland turbo c++ 3.0 simply because it
- was easy to do so. To get a speed increase I tried using Borland C++ 4.52
- which I bought a while back. Most of the new Borland stuff is much more
- complicated than needs be so I hadn't used it much, but I did get about an
- extra two FPS from the recompile.
-
- I also wrote a pascal version while teaching myself pascal on the IBMs.
-
- This is the 32-bit WATCOM version. While there is an older Borland 16-bit
- version (aliasc.c) and a Turbo Pascal version (aliaspas.pas) this is the
- only one that is currently being revised and improved.
-
- This program is designed for at least the 486 processors. Preferably pentiums.
-
- Probably it'll end up as some kind of tutorial one day.
-
- PLEASE READ ALIAS.TXT
-
- --MIN (rhymes with NIN)
-
- "the me that you know is now made up of wires
- and even when i'm right with you i'm so far away" --NIN
- */
-
- #include <stdlib.h>
- #include <conio.h>
- #include <malloc.h>
- #include <stdio.h>
- #include <time.h>
- #include <dos.h>
- #include <math.h>
- #include <mem.h>
-
- //general defines
- #define FALSE (1==0)
- #define TRUE (1==1)
-
- #define FAILURE 0
- #define SUCCESS 1
-
- typedef unsigned char byte;
- typedef unsigned short int word;
- typedef unsigned int dword;
-
- //prototypes
- void change_timer(void);
- void restore_timer(void);
-
- void mode_graphic(void);
- void mode_text(void);
-
- int LoadTestImage(char *name);
- void setup_fps(void);
- void print_fps(int fps);
-
- void bilinear(void);
- void trilinear(void);
- void hyperlinear(void);
- void color_bilinear(void);
- void color_trilinear(void);
- void color_hyperlinear(void);
-
- void copycomposite(void);
- void clearcomposite(void);
- //int lines(void);
-
-
- //TIMER
- #define PIT_FREQUENCY 0x1234DDL
- #define frequency 100
- #define counter PIT_FREQUENCY/frequency
-
- volatile int BIOS_ticks=0;
- volatile int second_ticks=0;
- volatile int second_flag=FALSE;
-
- void (__interrupt __far *prev_int_1c)();
-
- void __interrupt __far timerhandler()
- {
- BIOS_ticks+=counter;
- second_ticks++;
- if(BIOS_ticks>=0x10000) {
- BIOS_ticks=0;
- _chain_intr(prev_int_1c);
- }
- if(second_ticks>=100) {
- second_flag=TRUE;
- second_ticks=0;
- }
- outp(0x20,0x20);
- }
-
-
- void change_timer()
- {
- //swap out the BIOS handler for our own....
- prev_int_1c=_dos_getvect(0x1c);
- _dos_setvect(0x1c,timerhandler);
- //change the clock frequency to 100 per second
- outp(0x43,0x34);
- outp(0x40,(byte)(counter%256));
- outp(0x40,(byte)(counter/256));
- }
-
-
- void restore_timer()
- {
- //restore 18.2 frequency of PIT 0
- outp(0x43,0x34);
- outp(0x40,0);
- outp(0x40,0);
- //restore the BIOS tick handler
- _dos_setvect(0x1c,timerhandler);
- }
-
-
- //constant
- #define WIDTH 320
- #define HEIGHT 200
- #define WIDTH_CENTER 160
- #define HEIGHT_CENTER 100
- #define WIDTH_OFFSET 60
- #define HEIGHT_OFFSET 0
-
- #define W_WIDTH 200
- #define W_HEIGHT 200
- #define W_WIDTH_CENTER 100
- #define W_HEIGHT_CENTER 100
-
- #define W_LEFT 60
- #define W_RIGHT 260
- #define W_TOP 0
- #define W_BOTTOM 200
-
- #define T_WIDTH 256
- #define T_HEIGHT 256
- #define T_WIDTH_CENTER 128
- #define T_HEIGHT_CENTER 128
-
- #define T_LEFT 0
- #define T_RIGHT 256
- #define T_TOP 0
- #define T_BOTTOM 256
-
- char *G_BASE=(char *)(0xa0000); //graphics memory
-
-
- //GRAPHICS
- #define PI 3.14159
-
- char *texture;
- int *y320;
- char *composite;
- struct rgb_struct {
- byte red;
- byte green;
- byte blue;
- } *palette;
- byte *palette_matrix;
-
- typedef struct {
- //fileformat
- word type; //42 4d BM
- dword filesize; //36 fe
- word unused1;
- word unused2;
- dword offsetbits; //0c
- //info
- dword infosize;
- word width; //c8 00
- word w1;
- word height;
- word h1;
- word planes; //1
- byte bitcount; //8
- dword compression; //0
- dword imagesize; //00 00 fa 00
- dword xpels;
- dword ypels;
- dword colorsused;
- dword colorsimportant;
- byte u1;
- } bmp_struct;
-
-
- //
- void mode_graphic(void);
- #pragma aux mode_graphic = \
- "mov ax,13h" \
- "int 10h" \
- "mov dx,03c2h" \
- "mov al,0e3h" \
- "out dx,al" /* put it in square mode */ \
- "mov dx,0x3c6" \
- "mov ax,0xff" \
- "out dx,al" \
- "mov dx,0x3c8" \
- "mov al,0" \
- "out dx,al" \
- "mov dx,0x3c9" \
- "mov esi, [palette]" \
- "mov ecx,768" \
- "mgloop:" \
- "mov al,[esi]" \
- "out dx,al" \
- "inc esi" \
- "sub ecx,1" \
- "jnz mgloop" \
- modify [ax dx esi];
-
-
- void mode_text(void);
- #pragma aux mode_text = \
- "mov ax,3" \
- "int 10h" \
- modify [ax];
-
-
- //load in a grayscale 320x200 BMP
- int LoadTestImage(char *name)
- {
- FILE *bmp;
- int x,y;
- int n;
- byte *thrash;
- bmp_struct *bf;
- char *source,*destination;
- int w,h,w_src,h_src,w_dst,h_dst;
- int BWIDTH;
- struct rgba_struct {
- byte blue;
- byte green;
- byte red;
- byte alpha;
- } *temp_palette;
-
- //
- bmp=fopen(name,"rb");
- if(bmp==NULL) return FAILURE;
-
- //
- bf=(bmp_struct *)malloc(sizeof(bmp_struct));
- if(bf==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for BMP header.\n",farcoreleft());
- exit(FAILURE);
- }
- fread(bf,sizeof(bmp_struct),1,bmp);
-
- if(bf->bitcount!=8) {
- mode_text();
- printf("The bitmap must be 8-bit (256 color).\n");
- exit(FAILURE);
- }
-
- //PALETTE
- //from b-g-r-unused dword format to proper RGB 3byte.
- temp_palette=(void *)malloc(4*256);
- if(temp_palette==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for temp palette.\n",farcoreleft());
- exit(FAILURE);
- }
- fread(temp_palette,4*256,1,bmp);
- for(n=0;n<256;n++)
- {
- palette[n].red=(temp_palette[n].red>>2);
- palette[n].green=(temp_palette[n].green>>2);
- palette[n].blue=(temp_palette[n].blue>>2);
- }
- free(temp_palette);
-
- //TEXTURE
- //blackout texture
- memset(texture,0,T_WIDTH*T_HEIGHT);
-
- //thrash the dumb MS format...
- thrash=(byte *)malloc(bf->width*bf->height);
- if(thrash==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for temporary bitmap thrashing area.\n",farcoreleft());
- exit(FAILURE);
- }
- fread(thrash,bf->width*bf->height,1,bmp);
-
- //dword align
- if((bf->width&3)!=0)
- BWIDTH=bf->width+(4-(bf->width&3));
- else
- BWIDTH=bf->width;
-
- //compute picture along x
- w_src=0;
- w_dst=0;
- w=bf->width;
- if(w>T_WIDTH) { w_src=((w-T_WIDTH)>>1); w=T_WIDTH; }
- if(w<T_WIDTH) w_dst=(T_WIDTH-w)>>1;
-
- //compute along y
- h_src=0;
- h_dst=0;
- h=bf->height;
- if(h>T_HEIGHT) { h_src=((h-T_HEIGHT)>>1); h=T_HEIGHT; }
- if(h<T_HEIGHT) h_dst=((T_HEIGHT-h)>>1);
-
- //
- source=thrash+((bf->height-1)*BWIDTH)+w_src-(h_src*BWIDTH);
- destination=texture+w_dst+h_dst*T_WIDTH;
-
- for(y=0;y<h;y++)
- {
- memcpy(destination,source,w);
- source-=BWIDTH;
- destination+=T_WIDTH;
- }
- free(thrash);
-
- free(bf);
-
- fclose(bmp);
- return SUCCESS;
- }
-
-
- //fps
- byte fpsset[8][24]={
- " ###### ###### #### ",
- " # # # # # ",
- " # # # # ",
- " ##### ###### #### ",
- " # # # ",
- " # # # ",
- " # # # # ",
- " # # #### "
- };
-
- byte charset[10][8][8]={
- //0
- {" ##### ",
- " # #",
- " # #",
- " # #",
- " # #",
- " # #",
- " ##### ",
- " "},
- //1
- {" ## ",
- " # ",
- " # ",
- " # ",
- " # ",
- " # ",
- " ###",
- " "},
- //2
- {" #### ",
- " # #",
- " #",
- " ### ",
- " # ",
- " # #",
- " ##### ",
- " "},
- // 3
- {" ##### ",
- " # #",
- " #",
- " #### ",
- " #",
- " # #",
- " ##### ",
- " "},
- //4
- {" ## ",
- " # # ",
- " # # ",
- " ###### ",
- " # ",
- " # ",
- " ### ",
- " "},
- //5
- {" #######",
- " # ",
- " # ",
- " ###### ",
- " #",
- " # #",
- " ##### ",
- " "},
- //6
- {" ##### ",
- " # ",
- " # ",
- " ###### ",
- " # #",
- " # #",
- " ##### ",
- " "},
- //7
- {" ######",
- " # #",
- " # ",
- " # ",
- " # ",
- " # ",
- " # ",
- " "},
- //8
- {" ##### ",
- " # #",
- " # #",
- " ##### ",
- " # #",
- " # #",
- " ##### ",
- " "},
- //9
- {" ##### ",
- " # #",
- " # #",
- " ######",
- " #",
- " # ",
- " #### ",
- " "}
- };
-
-
- //setup the fps counter...
- void setup_fps()
- {
- int c,x,y;
- byte *vid=(byte *)composite+(8*WIDTH);
-
- //change the 0 to 9 charset from spaces and pound-signs
- //into 0 and 255 (ie, black and white).
- for(c=0;c<=9;c++)
- for(y=0;y<=7;y++)
- for(x=0;x<=7;x++)
- if(charset[c][y][x]=='#')
- charset[c][y][x]=255;
- else
- charset[c][y][x]=0;
-
- //draw a "FPS" right below where the fps will be.
- //yes, it's slow C code, but here that's ok.
- for(y=0;y<=7;y++)
- for(x=0;x<=23;x++)
- if(fpsset[y][x]=='#')
- vid[y*WIDTH+x]=255;
- else
- vid[y*WIDTH+x]=0;
- }
-
-
- //draw a counter number at the top left of the graphics screen
- void print_fps(int fps)
- {
- int digits=6;
- char s[16];
- int count=0;
- word x_offset=0;
- int c,x,y;
- byte *src,*dst;
-
- //
- sprintf(s,"%d",fps);
-
- //
- while((s[count]!=NULL)&&(count<digits)) {
- c=(s[count++]-'0');
- src=(byte *)charset+c*8*8;
- dst=(byte *)composite+x_offset;
- for(y=0;y<8;y++) {
- for(x=0;x<8;x++) {
- *dst=*src;
- dst++;
- src++;
- }
- dst+=WIDTH-8;
- }
- x_offset+=8;
- }
-
- //ok. we wrote out the digits. now cleanup anything left over from the
- //last time on the right. we assume no more than 6 digits MAX.
- dst=(char *)composite+x_offset;
- for(y=0;y<8;y++) {
- for(x=x_offset;x<digits*8;x++) {
- *dst++=0;
- }
- dst+=WIDTH-((digits*8)-x_offset);
- }
- }
-
-
- void show_colors(void)
- {
- byte *p;
- int n,w;
- //display the color palette for us under the "fps"
- p=(byte *)composite+WIDTH*16;
- for(n=0;n<64;n++,p+=WIDTH) {
- for(w=0;w<8;w++) {
- *(p+w)=n;
- *(p+w+8)=n+64;
- *(p+w+16)=n+128;
- *(p+w+24)=n+192;
- }
- }
- //show us the bilinear antialiasing matrix column0. It SHOULD be an
- //exact match to the color palette. :)
- p=(byte *)composite+WIDTH*(32+64);
- for(n=0;n<64;n++,p+=WIDTH) {
- for(w=0;w<8;w++) {
- *(p+w)=palette_matrix[n];
- *(p+w+8)=palette_matrix[n+64];
- *(p+w+16)=palette_matrix[n+128];
- *(p+w+24)=palette_matrix[n+192];
- }
- }
- }
-
-
- //this is the fixed-point version of the scaling/rotation routine.
- //since we want maximum speed while still remaining in C parts of this
- //may be hard to read compared to the general rotate/scale routine.
- //It is similiar to the mathematical version except it uses 16.16
- //fixed-point and computes an initial texture vector then does something
- //similiar to a two-level line drawing routine, ok?
- void FixedRotateScale(float scale, //the scaling factor
- float angle) //the rotation angle
- {
- int sinas=sin(-angle)*65536*scale;
- int cosas=cos(-angle)*65536*scale;
-
- //x' = cos(-angle)+sin(-angle)
- //y' = cos(-angle)-sin(-angle)
- int xc=T_WIDTH_CENTER*65536 - (W_HEIGHT_CENTER*(cosas+sinas));
- int yc=T_HEIGHT_CENTER*65536 - (W_WIDTH_CENTER*(cosas-sinas));
-
- int tx,ty;
- int x,y;
- int tempx,tempy;
- char *screen=composite+WIDTH_OFFSET+HEIGHT_OFFSET*WIDTH;
-
- for (y=0;y<W_HEIGHT;y++)
- {
- tx=xc; ty=yc;
- for(x=0;x<W_WIDTH;x++)
- {
- tempx=(tx>>16); tempy=(ty>>16);
- if( (tempx<T_LEFT) || //clip
- (tempx>=T_RIGHT) ||
- (tempy<T_TOP) ||
- (tempy>=T_BOTTOM) )
- screen[x]=0; //clip to black
- else
- screen[x]=texture[tempx+tempy*T_WIDTH]; //draw texel
-
- tx+=cosas; ty-=sinas;
- }
- screen+=WIDTH; xc+=sinas; yc+=cosas;
- }
- }
-
-
- //this is the revised floating-point version of the scaling/rotation routine.
- //now that I finally have a cpu that actually supports FPU op-code
- //(from a 486sx25 to a 486dx4-100) thought I'd try them out.
- //note that unlike the pure mathematical version, we compute the vector
- //of rotation just once at the beginning of the function.
- void FloatRotateScale(float scale, //the scaling factor
- float angle) //the rotation angle
- {
- float sinas=sin(-angle)*scale;
- float cosas=cos(-angle)*scale;
-
- //x' = cos(-angle)+sin(-angle)
- //y' = cos(-angle)-sin(-angle)
- float xc=T_WIDTH_CENTER - (W_HEIGHT_CENTER*(cosas+sinas));
- float yc=T_HEIGHT_CENTER - (W_WIDTH_CENTER*(cosas-sinas));
-
- float tx, ty;
- int x,y;
- //actually to composite buffer and not to screen...
- //but it can be changed easily.
- char *screen=composite+WIDTH_OFFSET+HEIGHT_OFFSET*WIDTH;
-
- for (y=0;y<W_HEIGHT;y++)
- {
- tx=xc; ty=yc;
- for (x=0;x<W_WIDTH;x++)
- {
- if( (tx<(float)T_LEFT) ||
- (tx>=(float)T_RIGHT) ||
- (ty<(float)T_TOP) ||
- (ty>=(float)T_BOTTOM) )
- screen[x]=0;
- else
- screen[x]=texture[(int)(tx)+(((int)ty)*T_WIDTH)];
-
- tx+=cosas; ty-=sinas;
- }
- screen+=WIDTH; xc+=sinas; yc+=cosas;
- }
- }
-
-
- //This is the pure mathematical version of rotation and scaling.
- //It is naturally slow since it has not be optimized to take advantage
- //of the way computers currently operate. Nevertheless it can help
- //some of you understand what is going on in the other routines.
- void MathematicalRotateScale(float scale,
- float angle)
- {
- //precompute the cosine and sine values used to speed things up
- float cosas=cos(angle)*scale;
- float sinas=sin(angle)*scale;
- float xc, yc;
- float tx, ty;
- int x,y;
- char *screen;
-
- for (y=0;y<W_HEIGHT;y++)
- {
- for (x=0;x<W_WIDTH;x++)
- {
- //compute the center of the texture bitmap
- xc=(float)(x-W_WIDTH_CENTER);
- yc=(float)(y-W_HEIGHT_CENTER);
-
- //compute the translation of x and y into texture map
- //x' = x*cos(angle) - y*sin(angle) +160
- //y' = x*sin(angle) + y*cos(angle) +100
- tx=( (xc * cosas) - (yc * sinas) ) + (float)T_WIDTH_CENTER;
- ty=( (xc * sinas) + (yc * cosas) ) + (float)T_HEIGHT_CENTER;
-
- //compute the pixel on the composite screen buffer to draw to
- screen=composite+(x+W_LEFT)+((y+W_TOP)*WIDTH);
-
- //clip to black any texels that fall off of our 320x200 map
- if( (tx<(float)T_LEFT) ||
- (tx>=(float)T_RIGHT) ||
- (ty<(float)T_TOP) ||
- (ty>=(float)T_BOTTOM) )
- *screen=0; //clipped to black
- else
- *screen=texture[ (int)(tx) + ( (int)(ty)*T_WIDTH) ]; //texel
- }
- }
- }
-
-
- //post bilinear antialiasing
- void bilinear()
- {
- int line, x;
- byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
- for(line=HEIGHT-2;line>0;line--) {
- for(x=W_WIDTH-2;x>0;x--) {
- *p=(( (*p) + ( ( *(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH) ) >>2 ) )>>1);
- p++;
- }
- p+=2*WIDTH_OFFSET+2;
- }
- }
-
-
- //post trilinear antialiasing
- void trilinear()
- {
- int line, x;
- byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1;
- for(line=HEIGHT-2;line>0;line--) {
- for(x=W_WIDTH-2;x>0;x--) {
- *p=(( (*p) + ( (*(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH)+*(p-WIDTH-1)+*(p-WIDTH+1)+*(p+WIDTH-1)+*(p+WIDTH+1)) >>3 ) )>>1);
- p++;
- }
- p+=2*WIDTH_OFFSET+2;
- }
- }
-
-
- //post hyperlinear? antialiasing. This is just an experiment.
- void hyperlinear()
- {
- int line, x;
- byte c;
- byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1;
- for(line=HEIGHT-2;line>0;line--) {
- for(x=W_WIDTH-2;x>0;x--) {
- c=(( (*p) + ( (*(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH)+*(p-WIDTH-1)+*(p-WIDTH+1)+*(p+WIDTH-1)+*(p+WIDTH+1)) >>3 ) )>>1);
- *(p-WIDTH-1)=c;
- *(p-WIDTH+1)=c;
- *(p+WIDTH-1)=c;
- *(p+WIDTH+1)=c;
- p++;
- }
- p+=2*WIDTH_OFFSET+2;
- }
- }
-
-
- //prime is the pixel in the center. fourth is one of the four sourrounding
- //pixels in bilinear antialiasing.
- void setup_matrix()
- {
- int match,diff;
- int d;
- int n;
- int prime,derv;
- int red,green,blue;
-
- for(derv=0;derv<256;derv++) {
- for(prime=0;prime<256;prime++) {
- //compute the color component differences for red,
- //green, and blue of the prime and the fourth.
- //this rgb is the weighted average of the prime and the fourth.
- red=(int)(palette[derv].red*.25+palette[prime].red*.75);
- green=(int)(palette[derv].green*.25+palette[prime].green*.75);
- blue=(int)(palette[derv].blue*.25+palette[prime].blue*.75);
-
- //find the closet color in the 256 color palette
- for(match=0,diff=3*256,n=0;n<256;n++) {
- d=abs(palette[n].red-red)+abs(palette[n].green-green)+abs(palette[n].blue-blue);
- if(d<diff) { match=n; diff=d; }
- }
-
- //add new entry to palette matrix
- palette_matrix[derv*256+prime]=match;
- }
- printf(".");
- }
- printf("\n");
- }
-
-
- //post bilinear antialiasing
- void color_bilinear()
- {
- int line, x;
- byte c,cc;
- byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
- for(line=HEIGHT-2;line>0;line--) {
- for(x=W_WIDTH-2;x>0;x--) {
- c=*p;
- c=palette_matrix[ c + ((*(p-1))<<8) ];
- c=palette_matrix[ c + ((*(p+1))<<8) ];
- c=palette_matrix[ c + ((*(p-WIDTH))<<8) ];
- c=palette_matrix[ c + ((*(p+WIDTH))<<8) ];
- *(p++)=c;
- }
- p+=2*WIDTH_OFFSET+2;
- }
- }
-
-
- //this is the original color bilinear antialiasing routine.
- //it works but is very slow.
- void accurate_color_bilinear()
- {
- int n,match,diff;
- int line,x;
- int red,green,blue;
- int d;
- byte c;
- byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
- for(line=HEIGHT-2;line>0;line--) {
- for(x=W_WIDTH-2;x>0;x--) {
- //
- c=*(p-1);
- red=palette[c].red;
- green=palette[c].green;
- blue=palette[c].blue;
-
- c=*(p+1);
- red+=palette[c].red;
- green+=palette[c].green;
- blue+=palette[c].blue;
-
- c=*(p-WIDTH);
- red+=palette[c].red;
- green+=palette[c].green;
- blue+=palette[c].blue;
-
- c=*(p+WIDTH);
- red+=palette[c].red;
- green+=palette[c].green;
- blue+=palette[c].blue;
-
- red=red>>2;
- green=green>>2;
- blue=blue>>2;
-
- c=*p;
- red+=palette[c].red;
- green+=palette[c].green;
- blue+=palette[c].blue;
-
- red=red>>1;
- green=green>>1;
- blue=blue>>1;
-
- //
- for(match=0,diff=1000,n=0;n<256;n++) {
- d=abs(palette[n].red-red)+abs(palette[n].green-green)+abs(palette[n].blue-blue);
- if(d<diff) { match=n; diff=d; }
- }
-
- //
- *p=match;
- p++;
- }
- p+=2*WIDTH_OFFSET+2;
- }
- }
-
-
- //copy the composite buffer to the VGA screen
- void copycomposite()
- {
- memcpy(G_BASE,composite,WIDTH*HEIGHT);
- }
-
-
- //clear the composite buffer
- void clearcomposite()
- {
- memset(composite,0,WIDTH*HEIGHT);
- }
-
-
- // "You had all of them on your side? didn't you?" --NIN
- int main(int argc,char *argv[])
- {
- float angle=PI/256.0;
- float angle_v=-PI/128.0;
- float scale=1.05;
- int n;
- int alias=0, render=0, grayscale=TRUE;
- int key='~',key2=0; //so as not to trip up the arrow keys below
- int frames=0;
-
- mode_text();
- printf("Scaling/Rotation/Antialiasing Prototyper by Minimalist 1995-1996.\n");
- // printf("Last compiled %s %s. %d lines of C code.\n",__DATE__,__TIME__,lines());
- #ifdef __WATCOMC__
- printf("Using 32-bit compiler Watcom C version %d.%d.\n\n",
- (__WATCOMC__)/100,(__WATCOMC__%100));
- #endif
-
- //you did specify a filename didn't you?
- if(argc!=2)
- {
- printf("Use: ALIASWC 'filename.bmp'\n");
- return(FAILURE);
- }
-
- printf("Allocating palette.\n");
- palette=(void *)malloc(3*256);
- if(palette==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for palette.\n",farcoreleft());
- exit(FAILURE);
- }
-
- printf("Allocating texture.\n");
- texture=(char *)malloc(T_WIDTH*T_WIDTH);
- if(texture==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for texture map.\n",farcoreleft());
- exit(FAILURE);
- }
-
- //create a composite buffer (off-screen double buffer)
- printf("Allocating composite buffer.\n");
- composite=(char *)malloc(WIDTH*HEIGHT);
- if(composite==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for composite buffer.\n",farcoreleft());
- exit(FAILURE);
- }
-
- //initialize our table of n*320
- printf("Allocating y320.\n Computing y[0,%d).\n",HEIGHT);
- y320=(int *)malloc(sizeof(int)*HEIGHT);
- if(y320==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for y320 table.\n",farcoreleft());
- exit(FAILURE);
- }
- for(n=0;n<HEIGHT;n++) y320[n]=n*WIDTH;
-
- printf("Load image [%s].\n",argv[1]);
- if(LoadTestImage(argv[1])==FAILURE)
- {
- mode_text();
- printf("The file %s does not exist.\n",argv[1]);
- return(FAILURE);
- }
-
- printf("Allocating palette_matrix.\n Computing Color Bilinear Antialiasing matrix");
- palette_matrix=(byte *)malloc(256*256);
- if(palette_matrix==NULL) {
- mode_text();
- // printf("Not enough memory (%lu) for y320 table.\n",farcoreleft());
- exit(FAILURE);
- }
- setup_matrix();
-
-
- //inpho
- mode_text();
- printf("Scaling/Rotation/Antialiasing Prototyper 3 by Minimalist 1995-1996.\n");
- // printf("Last compiled %s %s. %d lines of C code.\n",__DATE__,__TIME__,lines());
- #ifdef __WATCOMC__
- printf("Using 32-bit compiler Watcom C version %d.%d.\n\n",
- (__WATCOMC__)/100,(__WATCOMC__%100));
- #endif
- // printf("Memory %u. Stack %u.\n",_memavl(),stackavail());
- /*
- if(_control87)
- printf("FPU:%d87.",_8087);
- else
- printf("No FPU.");
- */
- //the propaganda
- printf("This program requires at least a 486 with an integrated 387 grade FPU\n");
- printf("and the DOS Extender DOS4GW.EXE or a compatible.\n");
-
- printf("You may use any of the following keys:\n");
- printf(" ESC will exit the program\n");
- printf(" C Color antialiasing\n");
- printf(" G Fast grayscale antialiasing\n");
-
- printf("Scaling and Rotation:\n");
- printf(" I Integer fixed-point Optimized\n");
- printf(" F Floating-point Optimized\n");
- printf(" M Mathematical floating-point\n");
-
- printf("Antialiasing Filters:\n");
- printf(" N No Antialiasing\n");
- printf(" B Post Bilinear Antialiasing\n");
- printf(" T Post Trilinear Antialiasing (GRAYSCALE ONLY)\n");
- printf(" H Post um... ghosting/Antialiasing? (GRAYSCALE ONLY)\n");
- printf(" A Accurate Bilinear Color Antialiasing (COLOR ONLY) (SLOW!)\n");
-
- printf("To rotate use left/right arrows. To scale use up/down arrows.\n");
- printf("Pressing Ctrl w/ arrows will increase speed. Use BACKSPACE to stop.\n\n");
-
- //wait for windows to quit thrashing the hard drive...
- printf("Press any key (except ESC) to start...\n");
- while (!kbhit()); getch();
-
- //set things up
- mode_graphic();
-
- clearcomposite();
- setup_fps();
- show_colors();
- change_timer();
-
- //the main loop
- while (key!=27) {
- if(kbhit()) {
- key=toupper(getch());
- switch (key) {
- //internal yazzie testing frame for...
- //and sissy
- case 'S':
- angle-=PI/4.0;
- angle_v=0.0;
- break;
- //and susy honey
- case 'U':
- angle+=PI/4.0;
- angle_v=0.0;
- break;
- //and prissy
- case 'Z':
- scale=0.5;
- angle=PI/2.0;
- angle_v=-0.1;
- break;
- //and yazzie :)
- case 'Y':
- angle=0.0;
- angle_v=0.0;
- scale=1.0;
- break;
-
- case 'I': render=0; break;
- case 'F': render=1; break;
- case 'M': render=2; break;
- case 'W': render=3; break;
-
- case 'N': alias=1; break;
- case 'B': alias=2; break;
- case 'T':
- case 'A': alias=3; break;
- case 'H': alias=4; break;
-
- case 'C': grayscale=FALSE; break;
- case 'G': grayscale=TRUE; break;
-
- case 0:
- key2=getch();
- switch (key2) {
- //rotation
- case 75: angle_v+=PI/256.0; break; //left arrow
- case 77: angle_v-=PI/256.0; break; //right arrow
- case 115: angle_v+=PI/32.0; break; //left arrow
- case 116: angle_v-=PI/32.0; break; //right arrow
- //scale
- case 72: scale-=0.05; break;
- case 80: scale+=0.05; break;
- case 141: scale-=0.5; break;
- case 145: scale+=0.5; break;
- }
- break;
- }
- }
-
- switch (render) {
- case 0: FixedRotateScale(scale,angle); break;
- case 1: FloatRotateScale(scale,angle); break;
- case 2: MathematicalRotateScale(scale,angle); break;
- }
-
- switch (grayscale) {
- case FALSE: {
- switch (alias) {
- //case 1: do nothing....
- case 2: color_bilinear(); break;
- case 3: accurate_color_bilinear(); break;
- }
- break;
- case TRUE: {
- switch (alias) {
- //case 1: do nothing....
- case 2: bilinear(); break;
- case 3: trilinear(); break;
- case 4: hyperlinear(); break;
- }
- break;
- }
- }
- }
-
- copycomposite(); //show us the composite buffer!
-
- angle+=angle_v;
- if(angle>2*PI) angle-=2*PI; //bound our angle...
- if(angle<-2*PI) angle+=2*PI;
-
- //do the FPS calcing
- frames++;
- if(second_flag) { //been a second yet?
- print_fps(frames); //yes, so see how many frames we've done in that time.
- second_flag=FALSE;
- frames=0; //and the frames
- }
- }
-
- //restore things to normal
- restore_timer();
- free(composite);
- free(palette);
- free(texture);
- free(y320);
- free(palette_matrix);
-
- //parting words....
- mode_text();
- printf("By Minimalist (Lewis A. Sellers) 1995-96. Part of the C/Pascal/Asm package.\n");
- printf("To contact, email: lsellers@1stresource.com (shortly to be lsellers@usit.net).\n");
- printf("or drop by http://www.dwc.edu/grail, site of Grail Operating System Project.\n\n");
-
- printf("#coders home page: http://www.realtime.net/~dlinvill/coders/index.html\n\n");
-
- printf("Psst. Testing out the original code or modification you did to it? Then press\n");
- printf("Z to set a standard scale and rotation factor. On a 486dx4 100mhz 256kb cache\n");
- printf("60ns DRAM, and an awful PCI Trio32 S3 graphics card:\n");
- printf(" I=~43fps F=~7fps M=~5fps\n");
- printf(" I/Grayscale Bilinear=~27fps Trilinear=~23fps Hyperlinear=~21.5fps\n");
- printf(" I/Color Bilinear=~19fps\n\n");
-
- printf(" 'It was men like me that built the bomb.' --paraphrased, T2\n\n");
-
- return(SUCCESS);
- }
-
-
- //cute trick of mine for single file programs
- //int lines() { return __LINE__+1; }
-